/*********************************************************************************
 *      Copyright:  (C) 2022 YanlinZhou<1222>
 *                  All rights reserved.
 *
 *       Filename:  main.c
 *    Description:  This file 
 *                 
 *        Version:  1.0.0(04/10/2022)
 *         Author:  YanlinZhou <1222>
 *      ChangeLog:  1, Release initial version on "04/10/2022 08:57:03 PM"
 *                 
 ********************************************************************************/
#include "log.h"
#include "main.h"
#define DEBUG 0 

int			g_stop; //break while(g_stop)

/* Command line parameter parsing struct */
struct option opts[]= 
{
	{ "ipaddr", required_argument, NULL, 'i' },
	{ "port",   required_argument, NULL, 'p' },
	{ "time",   required_argument, NULL, 't' },
	{ "deamon", no_argument,	   NULL, 'd' },
	{ "help",   no_argument,       NULL, 'h' },
	{0, 0, 0, 0}
};

int main (int argc, char **argv)
{
	char       				*progname = basename(argv[0]);
	int 					my_daemon = 0;				 // for if_daemon() function 
	int             		ch = 0;						 //for switch(ch)
	int 					rv = 0;						 //funtion return value 
	float					temp = 0;					 //temperature
	char 					*str = (char *)malloc(64);	 //to  save sample data string 
	struct my_time 			time_s;						 //current_time, last_time, tv
	struct sigaction 		action;						 //for signal 
	sqlite_info_t			sqlite_info;				 //table_name, database_name, db, db_str
	socket_info_t			sokt;						 //ip, port, connect_fd 

    time_s.last_time = 0;
	time_s.tv = 0;
	sokt.connect_fd = -1;
	sqlite_info.database_name = "temp.db";
	sqlite_info.table_name = "temp_tb";
	sqlite_info.db_str = (char*)malloc(128);
	
	/* Argument analysis */
	while( (ch=getopt_long(argc, argv, "i:p:t:dh", opts, NULL)) != -1 ) 
	{
		switch(ch) 
		{
			case 'i':
				sokt.server_ip = optarg;
				break;

			case 'p':
				sokt.server_port = atoi(optarg);
				break;

			case 't':
				time_s.sample_interval = atoi(optarg);
				break;

			case 'd':
				my_daemon = 1;
				break;

			case 'h':
				print_client_usage(argv[0]);
				return 0;
		}
	}

	if((!sokt.server_ip || !sokt.server_port || !time_s.sample_interval))
	{
		print_client_usage(argv[0]);
		return -1;
	}	
	
	printf ("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
	printf ("|\n");
	printf ("********************** Client start to run ****************\n");
	printf ("|\n");
	printf ("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");

	/* Install the signal */
	action.sa_handler = handle_pipe; 
	sigemptyset(&action.sa_mask);
	action.sa_flags = 0;

	signal(SIGTERM, sig_handle); /* for SIGTERM to print message befor quit program */
	signal(SIGINT, sig_handle);	/* for SIGTERM to print message befor quit program */
	sigaction(SIGPIPE, &action, NULL); /* for ignore  SIGPIPE preventing program exit */

	/* open mylog */
	if(DEBUG) //set set log to standard output for debug
	{
		if( logger_init("stdout", LOG_LEVEL_DEBUG) < 0 )
		{
			log_error("initial logger system failure\n");
			return -1;
		}

		log_info("ste program running on debug now!\n");
	}
	else //set log to log file 
	{
		if(logger_init("running.log", LOG_LEVEL_INFO) < 0)
		{
			log_error("initial logger system failure\n");
			return -2;
		}

		log_info("The system logs are recording!\n");
	}

	/* create_database */
	if( (rv = create_database(&sqlite_info.db, sqlite_info.database_name)) < 0 ) 
	{
		log_error("create_database failure:%s\n");
		return -3;
	}

	/* create_table */
	if( (rv = create_table(sqlite_info)) < 0 )
	{
		log_error("create_table failure!\n");
		return -4;
	}

	/* if run at deamon */
	if( (rv = if_daemon(my_daemon)) <0 )
	{
		log_error("if_daemon failure:%s\n", strerror(errno));
		return -5;
	}

	/* in a loop to determin_time and send_sample_data */
	log_debug("going to the loop!\n");
	while(!g_stop)
	{
		log_debug ("----------------the loop begin-----------------\n");

		if(determin_time(&time_s))
		{
			log_debug ("Now time is:%s", ctime(&time_s.current_time));
			if( (rv = get_temperature( &temp) ) < 0 )
			{
				log_error(  "Get temperature failure! rv = %d\n", rv);
//				return -6;
			}

			log_debug("get temperature sucessfully: %f\n", temp);

			sprintf(str, "%s/%f/%s\n", "No.1_Machine", temp, ctime(&time_s.current_time));
			log_debug("str = : %s\n", str);

            log_debug("str before if(connect_fd<0) reconnect_fd :%d\r\n",sokt.connect_fd);

			if(sokt.connect_fd < 0) /* is not connected to server */
			{
				log_debug("Client try to reconnect to server!\n");
				log_debug ("before reconnect in the  if(connect_fd) the connect_fd is :%d\n\n", sokt.connect_fd);

				sokt.connect_fd = socket_client_init( &sokt ); /* reconnect */	
				if(sokt.connect_fd > 0)
				{
					log_info("reconnect sucessfully!\n");
				}

				log_debug ("after reconnect the connect_fd is %d:\n\n",sokt.connect_fd );

				if(sokt.connect_fd >= 0) /* reconnect sucessfully */
				{
					if( (rv = send_sample_data_if_failure_save_to_db(&sokt, sqlite_info, str, temp, ctime(&time_s.tv))) <0 )
					{
						log_error(  "send_sample_data_if_failure_save_to_db failure:%s\n", strerror(errno));
						continue;
					}

			  		printf ("Client send sample data sucessfully at %s\n", ctime(&time_s.tv));
			  		log_info ("Client send sample data sucessfully!\n");

					continue;
				}
				else /* reconnect failure save data into the database and goto determin_time */
				{
						if( (rv = client_save_data(sqlite_info, temp, ctime(&time_s.tv))) < 0 ) 
						{
							log_error(  "client_save_data failure:%s",strerror(errno));
							continue;

						}

						log_info("reconnect failure save data into the database sucessfully!\n");
						continue;
				}

			}
			else /* is connected */
			{
				if( (rv = send_sample_data_if_failure_save_to_db(&sokt, sqlite_info, str, temp, ctime(&time_s.tv))) <0 )
                {
					log_error(  "send_sample_data_if_failure_save_to_db failure:%s\n", strerror(errno));
					continue;
				}

			  	printf ("Client send sample data sucessfully at %s\n", ctime(&time_s.tv));
			  	log_info ("Client send sample data sucessfully !\n");
				continue;
			}

		}

		else/* ampling time has not arrived */
		{
			if(sokt.connect_fd < 0) /* if not connected to server reconnect to server */
			{
				log_debug("Client try to reconnect to server!\n");
				log_debug ("before reconnect in the  if(connect_fd) the connect_fd is :%d\n\n", sokt.connect_fd);

				sokt.connect_fd = socket_client_init( &sokt ); /* reconnect */	
				if(sokt.connect_fd > 0)
				{
					log_info("reconnect sucessfully!\n");
				}

				log_debug ("after reconnect the connect_fd is %d:\n\n",sokt.connect_fd );
			}

			if(sokt.connect_fd >0)
			{
				/* judge the database if empty and to send the first roll of the database if database has data  */
			    if( (rv = inquire_first_row(&sqlite_info)) <0 )
   				{   
				  log_error("inquire_first_row function call select first row failure%s\n");
       		      continue; 
       		 	}   
			    else if( 1==rv ) 
			    {   
   		   		  /* send_database_first_roll */
      			  if( (rv = send_table_first_roll(&sokt, sqlite_info.db_str)) < 0 ) 
      			  {
//					  log_error("send_database_first_roll function call failure\n");
          			  continue; 
				  }
	
				  printf ("Client send database table's first record sucessfully at %s\n", ctime(&time_s.tv));
				  log_info("Client send database table's first record sucessfully!i\n");
				  /* delete database first row */
				  if ( rv = (delete_db_first_record(sqlite_info)) <0 )
				  {
					  log_debug("delete_db_first_record failure:%s\n", strerror(errno));
					  continue;
				  }

				  printf ("Client delete database table's first record sucessfully at %s\n", ctime(&time_s.tv));
				  log_info("Client delete database table's first record sucessfully!\n");
				  continue;
			    }

	 		    else
				{   
//			 		printf ("the database is empty\n");
    	 			continue;
				}
			}

			else /* reconnect failure */
			{
				continue;
			}

		}

		log_info("Log going to stop!");
		logger_term();

		return 0;
	}

}


void sig_handle(int signum)
{
    printf("The program of sample temperature is terminated!\n");
    g_stop = 1;
}

int determin_time(struct my_time *t)
{
    t->current_time = time(&t->tv);
    if((t->current_time - t->last_time) > t->sample_interval)
    {
        t->last_time = t->current_time;
        return 1;
    }
    else
    {
        return 0;
    }
	return 0;
}

int if_daemon(int sw)
{
	if(sw)
	{
		printf ("The process is going to running at daemon!\n");
		if( daemon(0, 0) < 0)
   		{
       		 printf("Program deamon() failure: %s\n",strerror(errno));
       		 return -1;
   		}
		return 1;
	}
	return 1;
}

void handle_pipe(int sig)
{
	;
}

int send_sample_data_if_failure_save_to_db(socket_info_t *sokt, sqlite_info_t sqlite_info, char *str, float temperature, char *time)
{
	int rv = -1;
    log_debug("reconnect  sucessfully and to  send temperature\n");
	if( (rv = send_sample_data(sokt, str)) < 0 ) /* send_sample_data failure*/
    {
        printf("client send_sample_data failure:%s\n", strerror(errno));
		return -1;
        if( (rv = client_save_data(sqlite_info, temperature, time)) < 0 )
        {
			printf ("client_save_data into database failure:%s\n", strerror(errno));
            return -2;
        }
        log_info("client_save_data into database sucessfully!");
        return 1;
	}
	return 1;
}

